//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Eas.WebCrawler.Test.PlugIns {
    /// <summary>
    /// Summary description for UrlProcessorTest
    /// </summary>
    [TestClass]
    public class UrlProcessorTest {
        public UrlProcessorTest() {
            //
            // TODO: Add constructor logic here
            //
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize() { fireCount = 0; TestDirectoryHelper.Setup(); }
        //
        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup() { TestDirectoryHelper.TearDown(); }
        //
        #endregion

        [TestMethod]
        /// <summary>Executes the TestDoNothingProcessor test.</summary>
        public void TestDoNothingProcessor() {
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.DoNothingUrlProcessedHandler handler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.DoNothingUrlProcessedHandler();
            handler.UrlProcessed(null, new Eas.WebCrawler.Interfaces.UrlCompletedEventArgs(null, null));
        }

        [TestMethod]
        /// <summary>Executes the TestEventFiringProcessor test.</summary>
        public void TestEventFiringProcessor() {
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.EventFiringUrlProcessedHandler handler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.EventFiringUrlProcessedHandler();
            handler.OnUrlProcessed += new EventHandler<Eas.WebCrawler.Interfaces.UrlCompletedEventArgs>(Fired);
            handler.UrlProcessed(null, CreateArgs(4, false, RequestHelper.rGoogle, null));
            Assert.AreEqual<int>(1, fireCount);
        }

        [TestMethod]
        /// <summary>Executes the DelegatingEventTest test.</summary>
        public void DelegatingEventTest() {
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.EventFiringUrlProcessedHandler handler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.EventFiringUrlProcessedHandler();
            handler.OnUrlProcessed += new EventHandler<Eas.WebCrawler.Interfaces.UrlCompletedEventArgs>(Fired);
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.DelegatingUrlProcessedHandler outerHandler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.DelegatingUrlProcessedHandler(handler);
            Assert.AreSame(handler, outerHandler.InnerHandler);
            outerHandler.UrlProcessed(null, CreateArgs(4, false, RequestHelper.rGoogle, null));
            Assert.AreEqual<int>(1, fireCount);
        }

        [TestMethod]
        /// <summary>Executes the ConditionalTextTest test.</summary>
        public void ConditionalTextTest() {
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.FileSavingUrlProcessedHandler fileHandler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.FileSavingUrlProcessedHandler(TestDirectoryHelper.SourceDir, new Eas.WebCrawler.PlugIns.FileNamers.SimpleUrlNamer());
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.VisitedListCreatingUrlProcessor listHandler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.VisitedListCreatingUrlProcessor(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"));
            Assert.AreEqual<string>(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), listHandler.FileName);
            Assert.AreEqual<System.IO.DirectoryInfo>(TestDirectoryHelper.SourceDir, fileHandler.BaseSaveDirectory);
            Assert.IsNotNull(fileHandler.FileNamer);
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.ConditionalUrlProcessor conditionalHander = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.ConditionalUrlProcessor(listHandler, fileHandler, new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.UrlSelectionDelegate((Eas.WebCrawler.PlugIns.UrlProcessedHandlers.UrlSelectionDelegate)delegate(Eas.WebCrawler.Interfaces.UrlCompletedEventArgs argument) { return argument.State.IsTextResponse; }));
            Assert.AreSame(fileHandler, conditionalHander.FalseConditionHandler);
            Assert.AreSame(listHandler, conditionalHander.TrueConditionHandler);
            using (Eas.WebCrawler.Interfaces.TemporaryStorage store = CreateTextStore()) {
                using (Eas.WebCrawler.Interfaces.TemporaryStorage store2 = CreateTextStore()) {
                    conditionalHander.UrlProcessed(null, CreateArgs(4, true, new Eas.WebCrawler.Interfaces.Request("http://www.google.com/erik.aspx"), store));
                    conditionalHander.UrlProcessed(null, CreateArgs(4, true, new Eas.WebCrawler.Interfaces.Request("http://www.google.com/saltwell.aspx"), store2));
                    Assert.IsTrue(System.IO.File.Exists(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt")));
                    int i = 0;
                    foreach (string line in Eas.WebCrawler.Common.IO.TextLineEnumerator.Create(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), true, true)) {
                        ++i;
                        if (i == 1)
                            Assert.AreEqual<string>("http://www.google.com/erik.aspx", line);
                        else
                            Assert.AreEqual<string>("http://www.google.com/saltwell.aspx", line);
                    }
                    Assert.AreEqual<int>(2, i);
                }
            }
            using (Eas.WebCrawler.Interfaces.TemporaryStorage store3 = CreateBinaryStore()) {
                conditionalHander.UrlProcessed(null, CreateArgs(6, false, new Eas.WebCrawler.Interfaces.Request("http://www.saltwell.com/eriksalt.aspx"), store3));
            }
            Assert.IsTrue(System.IO.File.Exists(TestDirectoryHelper.Name(TestDirectory.Source, "eriksalt.aspx")));
            using (System.IO.Stream stream = new System.IO.FileStream(TestDirectoryHelper.Name(TestDirectory.Source, "eriksalt.aspx"), System.IO.FileMode.Open)) {
                using (System.IO.BinaryReader reader = new System.IO.BinaryReader(stream)) {
                    byte[] buffer = reader.ReadBytes(10000);
                    string result = new string(System.Text.ASCIIEncoding.ASCII.GetChars(buffer));
                    Assert.AreEqual<string>("erik", result);
                }
            }
        }


        [TestMethod]
        /// <summary>Executes the Test LinkLestProcessor test.</summary>
        public void LinkLestProcessor() {
            Eas.WebCrawler.Interfaces.LinkSelector selector = new Eas.WebCrawler.PlugIns.Selectors.NameSelector(Eas.WebCrawler.PlugIns.Selectors.ConstantSelector.TrueSelector, Eas.WebCrawler.PlugIns.Selectors.ConstantSelector.FalseSelector, "yes");
            Eas.WebCrawler.Interfaces.LinkExtractor extractor = new Eas.WebCrawler.PlugIns.LinkExtractors.HtmlLinkExtractor();
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.LinkListCreatingUrlProcessor listHandler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.LinkListCreatingUrlProcessor(extractor, selector, TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"));
            Assert.AreEqual<string>(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), listHandler.FileName);

            Assert.AreSame(selector, listHandler.Selector);
            Assert.AreSame(extractor, listHandler.Extractor);

            using (Eas.WebCrawler.Interfaces.TemporaryStorage store = CreateTestStore()) {
                listHandler.UrlProcessed(null, CreateArgs(4, true, new Eas.WebCrawler.Interfaces.Request("http://www.google.com/erik.aspx"), store));
                Assert.IsTrue(System.IO.File.Exists(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt")));
                int i = 0;
                foreach (string line in Eas.WebCrawler.Common.IO.TextLineEnumerator.Create(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), true, true)) {
                    ++i;
                    bool erik_aspx = false;
                    bool yes_aspx = false;
                    if (line == "http://www.google.com/yes.aspx") {
                        Assert.IsFalse(yes_aspx);
                        yes_aspx = true;
                    }
                    else if (line == "http://www.yes.com/erik.aspx") {
                        Assert.IsFalse(erik_aspx);
                        erik_aspx = true;
                    }
                }
                Assert.AreEqual<int>(2, i);
            }
        }

        [TestMethod]
        /// <summary>Executes the TestAlreadyExistingUrlsInLinkListTest test.</summary>
        public void TestAlreadyExistingUrlsInLinkListTest() {
            Dictionary<Uri, object> uris = new Dictionary<Uri, object>();
            uris.Add(new Uri("http://www.google.com/yes.aspx"), null);
            Eas.WebCrawler.Interfaces.LinkSelector selector = new Eas.WebCrawler.PlugIns.Selectors.NameSelector(Eas.WebCrawler.PlugIns.Selectors.ConstantSelector.TrueSelector, Eas.WebCrawler.PlugIns.Selectors.ConstantSelector.FalseSelector, "yes");
            Eas.WebCrawler.Interfaces.LinkExtractor extractor = new Eas.WebCrawler.PlugIns.LinkExtractors.HtmlLinkExtractor();
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.LinkListCreatingUrlProcessor listHandler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.LinkListCreatingUrlProcessor(extractor, selector, TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), uris);
            Assert.AreEqual<string>(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), listHandler.FileName);

            Assert.AreSame(selector, listHandler.Selector);
            Assert.AreSame(extractor, listHandler.Extractor);
            Assert.AreSame(uris, listHandler.AlreadyListedUris);

            using (Eas.WebCrawler.Interfaces.TemporaryStorage store = CreateTestStore()) {
                listHandler.UrlProcessed(null, CreateArgs(4, true, new Eas.WebCrawler.Interfaces.Request("http://www.google.com/erik.aspx"), store));
                Assert.IsTrue(System.IO.File.Exists(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt")));
                int i = 0;
                foreach (string line in Eas.WebCrawler.Common.IO.TextLineEnumerator.Create(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), true, true)) {
                    ++i;
                    Assert.AreEqual<string>("http://www.yes.com/erik.aspx", line);
                }
                Assert.AreEqual<int>(1, i);
            }

        }


        [TestMethod]
        /// <summary>Executes the TestConditional2 test.</summary>
        public void TestConditional2() {
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.FileSavingUrlProcessedHandler fileHandler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.FileSavingUrlProcessedHandler(TestDirectoryHelper.SourceDir, new Eas.WebCrawler.PlugIns.FileNamers.SimpleUrlNamer());
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.VisitedListCreatingUrlProcessor listHandler = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.VisitedListCreatingUrlProcessor(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"));
            Assert.AreEqual<string>(TestDirectoryHelper.Name(TestDirectory.Source, "list.txt"), listHandler.FileName);
            Assert.AreEqual<System.IO.DirectoryInfo>(TestDirectoryHelper.SourceDir, fileHandler.BaseSaveDirectory);
            Assert.IsNotNull(fileHandler.FileNamer);
            Eas.WebCrawler.PlugIns.UrlProcessedHandlers.ConditionalUrlProcessor conditionalHander = new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.ConditionalUrlProcessor(listHandler, fileHandler, new Eas.WebCrawler.PlugIns.UrlProcessedHandlers.UrlSelectionDelegate((Eas.WebCrawler.PlugIns.UrlProcessedHandlers.UrlSelectionDelegate)delegate(Eas.WebCrawler.Interfaces.UrlCompletedEventArgs argument) { return !argument.State.IsTextResponse; }));
            Assert.AreSame(fileHandler, conditionalHander.FalseConditionHandler);
            Assert.AreSame(listHandler, conditionalHander.TrueConditionHandler);
            using (Eas.WebCrawler.Interfaces.TemporaryStorage store = CreateTextStore()) {
                using (Eas.WebCrawler.Interfaces.TemporaryStorage store2 = CreateTextStore()) {
                    conditionalHander.UrlProcessed(null, CreateArgs(4, true, new Eas.WebCrawler.Interfaces.Request("http://www.google.com/saltwell.aspx"), store2));
                }
                Assert.IsTrue(System.IO.File.Exists(TestDirectoryHelper.Name(TestDirectory.Source, "saltwell.aspx")));
                using (System.IO.StreamReader reader = new System.IO.StreamReader(TestDirectoryHelper.Name(TestDirectory.Source, "saltwell.aspx"))) {
                    Assert.AreEqual<string>("erik", reader.ReadToEnd());
                }

            }
        }

        private Eas.WebCrawler.Interfaces.TemporaryStorage CreateTestStore() {
            Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage store = new Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage();
            using (System.IO.TextWriter writer = store.GetTextWriter()) {
                using (System.IO.TextReader reader = new System.IO.StreamReader(TestDirectoryHelper.Name(TestDirectory.Source, "LinkList.htm"))) {
                    Eas.WebCrawler.Common.IO.StreamCopier.CopyTextStreams(reader, writer, 500);
                }
            }
            return store;
        }

        private Eas.WebCrawler.Interfaces.TemporaryStorage CreateTextStore() {
            Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage store = new Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage();
            using (System.IO.TextWriter writer = store.GetTextWriter()) {
                writer.Write("erik");
            }

            return store;
        }

        private Eas.WebCrawler.Interfaces.TemporaryStorage CreateBinaryStore() {
            Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage store = new Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage();
            using (System.IO.BinaryWriter writer = store.GetBinaryWriter()) {
                byte[] buffer = System.Text.ASCIIEncoding.ASCII.GetBytes("erik");
                writer.Write(buffer, 0, buffer.Length);
            }

            return store;
        }

        int fireCount = 0;

        public Eas.WebCrawler.Interfaces.UrlCompletedEventArgs CreateArgs(int id, bool isText, Eas.WebCrawler.Interfaces.Request request, Eas.WebCrawler.Interfaces.TemporaryStorage store) {
            TestProcessingState state = new TestProcessingState(id, isText, false, Eas.WebCrawler.Interfaces.WorkerState.Working);
            state._Request = request;
            state._ResponseStream = new System.IO.MemoryStream();
            return new Eas.WebCrawler.Interfaces.UrlCompletedEventArgs(state, store);
        }

        public void Fired(object sender, Eas.WebCrawler.Interfaces.UrlCompletedEventArgs argument) {
            fireCount++;
        }

    }
}
